home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / Auth.php < prev    next >
Encoding:
PHP Script  |  2006-04-07  |  29.2 KB  |  1,089 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
  3.  
  4. /**
  5.  * The main include file for Auth package
  6.  *
  7.  * PHP versions 4 and 5
  8.  *
  9.  * LICENSE: This source file is subject to version 3.01 of the PHP license
  10.  * that is available through the world-wide-web at the following URI:
  11.  * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
  12.  * the PHP License and are unable to obtain it through the web, please
  13.  * send a note to license@php.net so we can mail you a copy immediately.
  14.  *
  15.  * @category   Authentication
  16.  * @package    Auth
  17.  * @author     Martin Jansen <mj@php.net>
  18.  * @author     Adam Ashley <aashley@php.net>
  19.  * @copyright  2001-2006 The PHP Group
  20.  * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  21.  * @version    CVS: $Id: Auth.php,v 1.101 2006/03/02 06:53:08 aashley Exp $
  22.  * @link       http://pear.php.net/package/Auth
  23.  */
  24.  
  25. /**
  26.  * Returned if session exceeds idle time
  27.  */
  28. define('AUTH_IDLED',                    -1);
  29. /**
  30.  * Returned if session has expired
  31.  */
  32. define('AUTH_EXPIRED',                  -2);
  33. /** 
  34.  * Returned if container is unable to authenticate user/password pair
  35.  */
  36. define('AUTH_WRONG_LOGIN',              -3);
  37. /**
  38.  * Returned if a container method is not supported.
  39.  */
  40. define('AUTH_METHOD_NOT_SUPPORTED',     -4);
  41. /**
  42.  * Returned if new Advanced security system detects a breach
  43.  */
  44. define('AUTH_SECURITY_BREACH',          -5);
  45.  
  46. /**
  47.  * PEAR::Auth
  48.  *
  49.  * The PEAR::Auth class provides methods for creating an
  50.  * authentication system using PHP.
  51.  *
  52.  * @category   Authentication
  53.  * @package    Auth
  54.  * @author     Martin Jansen <mj@php.net>
  55.  * @author     Adam Ashley <aashley@php.net>
  56.  * @copyright  2001-2006 The PHP Group
  57.  * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  58.  * @version    Release: 1.3.0  File: $Revision: 1.101 $
  59.  * @link       http://pear.php.net/package/Auth
  60.  */
  61. class Auth {
  62.  
  63.     // {{{ properties
  64.  
  65.     /**
  66.      * Auth lifetime in seconds
  67.      *
  68.      * If this variable is set to 0, auth never expires
  69.      *
  70.      * @var  integer
  71.      * @see  setExpire(), checkAuth()
  72.      */
  73.     var $expire = 0;
  74.  
  75.     /**
  76.      * Has the auth session expired?
  77.      *
  78.      * @var   bool
  79.      * @see   checkAuth()
  80.      */
  81.     var $expired = false;
  82.  
  83.     /**
  84.      * Maximum idletime in seconds
  85.      *
  86.      * The difference to $expire is, that the idletime gets
  87.      * refreshed each time checkAuth() is called. If this
  88.      * variable is set to 0, idletime is never checked.
  89.      *
  90.      * @var integer
  91.      * @see setIdle(), checkAuth()
  92.      */
  93.     var $idle = 0;
  94.  
  95.     /**
  96.      * Is the maximum idletime over?
  97.      *
  98.      * @var boolean
  99.      * @see checkAuth()
  100.      */
  101.     var $idled = false;
  102.  
  103.     /**
  104.      * Storage object
  105.      *
  106.      * @var object
  107.      * @see Auth(), validateLogin()
  108.      */
  109.     var $storage = '';
  110.  
  111.     /**
  112.      * User-defined function that creates the login screen
  113.      *
  114.      * @var string
  115.      */
  116.     var $loginFunction = '';
  117.  
  118.     /**
  119.      * Should the login form be displayed
  120.      *
  121.      * @var   bool
  122.      * @see   setShowlogin()
  123.      */
  124.     var $showLogin = true;
  125.     
  126.     /**
  127.       * Is Login Allowed from this page
  128.       *
  129.       * @var  bool
  130.       * @see setAllowLogin
  131.       */
  132.     var $allowLogin = true;
  133.  
  134.     /**
  135.      * Current authentication status
  136.      *
  137.      * @var string
  138.      */
  139.     var $status = '';
  140.  
  141.     /**
  142.      * Username
  143.      *
  144.      * @var string
  145.      */
  146.     var $username = '';
  147.  
  148.     /**
  149.      * Password
  150.      *
  151.      * @var string
  152.      */
  153.     var $password = '';
  154.  
  155.     /**
  156.      * Login callback function name
  157.      *
  158.      * @var string
  159.      * @see setLoginCallback()
  160.      */
  161.     var $loginCallback = '';
  162.  
  163.     /**
  164.      * Failed Login callback function name
  165.      *
  166.      * @var string
  167.      * @see setLoginFailedCallback()
  168.      */
  169.     var $loginFailedCallback = '';
  170.  
  171.     /**
  172.      * Logout callback function name
  173.      *
  174.      * @var string
  175.      * @see setLogoutCallback()
  176.      */
  177.     var $logoutCallback = '';
  178.  
  179.     /**
  180.      * Auth session-array name
  181.      *
  182.      * @var string
  183.      */
  184.     var $_sessionName = '_authsession';
  185.  
  186.     /**
  187.      * Package Version
  188.      *
  189.      * @var string
  190.      */
  191.     var $version = "@version@";
  192.  
  193.     /**
  194.      * Flag to use advanced security
  195.      * When set extra checks will be made to see if the 
  196.      * user's IP or useragent have changed across requests. 
  197.      * Turned off by default to preserve BC.
  198.      *
  199.      * @var boolean
  200.      */     
  201.     var $advancedsecurity = false;
  202.  
  203.     /**
  204.      * Username key in POST array
  205.      *
  206.      * @var string
  207.      */
  208.     var $_postUsername = 'username';
  209.  
  210.     /**
  211.      * Password key in POST array
  212.      *
  213.      * @var string
  214.      */
  215.     var $_postPassword = 'password';
  216.  
  217.     /**
  218.      * Holds a reference to the session auth variable
  219.      * @var array
  220.      */
  221.     var $session;
  222.  
  223.     /**
  224.      * Holds a reference to the global server variable
  225.      * @var array
  226.      */
  227.     var $server;
  228.  
  229.     /**
  230.      * Holds a reference to the global post variable
  231.      * @var array
  232.      */
  233.     var $post;
  234.  
  235.     /**
  236.      * Holds a reference to the global cookie variable
  237.      * @var array
  238.      */
  239.     var $cookie;
  240.  
  241.     /**
  242.      * A hash to hold various superglobals as reference
  243.      * @var array
  244.      */
  245.     var $authdata;
  246.     
  247.     /**
  248.       * How many times has checkAuth been called
  249.       * var int
  250.       */
  251.     var $authChecks = 0;
  252.  
  253.     // }}}
  254.     // {{{ Auth() [constructor]
  255.  
  256.     /**
  257.      * Constructor
  258.      *
  259.      * Set up the storage driver.
  260.      *
  261.      * @param string    Type of the storage driver
  262.      * @param mixed     Additional options for the storage driver
  263.      *                  (example: if you are using DB as the storage
  264.      *                   driver, you have to pass the dsn string here)
  265.      *
  266.      * @param string    Name of the function that creates the login form
  267.      * @param boolean   Should the login form be displayed if neccessary?
  268.      * @return void
  269.      */
  270.     function Auth($storageDriver, $options = '', $loginFunction = '', $showLogin = true)
  271.     {
  272.         $this->applyAuthOptions($options);
  273.  
  274.         // Start the session suppress error if already started
  275.         if(!session_id()){
  276.             @session_start();
  277.             if(!session_id()) {
  278.                 // Throw error
  279.                 include_once 'PEAR.php';
  280.                 PEAR::throwError('Session could not be started by Auth, '
  281.                         .'possibly headers are already sent, try putting '
  282.                         .'ob_start in the begninig of your script');
  283.             }
  284.         }
  285.  
  286.         // Make Sure Auth session variable is there
  287.         if(   !isset($_SESSION[$this->_sessionName]) 
  288.            && !isset($GLOBALS['HTTP_SESSION_VARS'][$this->_sessionName])) {
  289.             session_register($this->_sessionName);
  290.         }
  291.  
  292.         // Assign Some globals to internal references, this will replace _importGlobalVariable
  293.         isset($_SESSION) 
  294.             ? $this->session =& $_SESSION[$this->_sessionName] 
  295.             : $this->session =& $GLOBALS['HTTP_SESSION_VARS'][$this->_sessionName] ;
  296.         isset($_SERVER) 
  297.             ? $this->server =& $_SERVER 
  298.             : $this->server =& $GLOBALS['HTTP_SERVER_VARS'];
  299.         isset($_POST) 
  300.             ? $this->post =& $_POST 
  301.             : $this->post =& $GLOBALS['HTTP_POST_VARS'];
  302.         isset($_COOKIE) 
  303.             ? $this->cookie =& $_COOKIE 
  304.             : $this->cookie =& $GLOBALS['HTTP_COOKIE_VARS'];
  305.         //isset($_GET) ? $var = &$_GET : $var = &$GLOBALS['HTTP_GET_VARS'];
  306.  
  307.         if ($loginFunction != '' && is_callable($loginFunction)) {
  308.             $this->loginFunction = $loginFunction;
  309.         }
  310.  
  311.         if (is_bool($showLogin)) {
  312.             $this->showLogin = $showLogin;
  313.         }
  314.  
  315.         if (is_object($storageDriver)) {
  316.             $this->storage =& $storageDriver;
  317.             // Pass a reference to auth to the container, ugly but works
  318.             // this is used by the DB container to use method setAuthData not staticaly.
  319.             $this->storage->_auth_obj =& $this;
  320.         } else {
  321.             // $this->storage = $this->_factory($storageDriver, $options);
  322.             // 
  323.             $this->storage_driver = $storageDriver;
  324.             $this->storage_options =& $options;
  325.         }
  326.     }
  327.  
  328.     // }}}
  329.     // {{{ applyAuthOptions()
  330.  
  331.     /**
  332.       * Set the Auth options 
  333.       *
  334.       * Some options which are Auth specific will be applied
  335.       * the rest will be left for usage by the container
  336.       * 
  337.       * @param array    An array of Auth options
  338.       * @return array   The options which were not applied
  339.       * @access private
  340.       */
  341.     function &applyAuthOptions(&$options)
  342.     {
  343.         if(is_array($options)){
  344.             if (!empty($options['sessionName'])) {
  345.                 $this->_sessionName = $options['sessionName'];
  346.                 unset($options['sessionName']);
  347.             }
  348.             if (!empty($options['allowLogin'])) {
  349.                 $this->allowLogin = $options['allowLogin'];
  350.                 unset($options['allowLogin']);
  351.             }
  352.             if (!empty($options['postUsername'])) {
  353.                 $this->_postUsername = $options['postUsername'];
  354.                 unset($options['postUsername']);
  355.             }
  356.             if (!empty($options['postPassword'])) {
  357.                 $this->_postPassword = $options['postPassword'];
  358.                 unset($options['postPassword']);
  359.             }
  360.             if (!empty($options['advancedsecurity'])) {
  361.                 $this->advancedsecurity = $options['advancedsecurity'];
  362.                 unset($options['advancedsecurity']);
  363.             }
  364.         }
  365.         return($options);
  366.     }
  367.  
  368.     // }}}
  369.     // {{{ _loadStorage()
  370.     
  371.     /**
  372.       * Load Storage Driver if not already loaded
  373.       *
  374.       * Suspend storage instantiation to make Auth lighter to use 
  375.       * for calls which do not require login
  376.       *
  377.       * @return bool    True if the conainer is loaded, false if the container
  378.       *                 is already loaded
  379.       * @access private
  380.       */
  381.     function _loadStorage()
  382.     {
  383.         if(!is_object($this->storage)) {
  384.             $this->storage =& $this->_factory($this->storage_driver, 
  385.                     $this->storage_options);
  386.             $this->storage->_auth_obj =& $this;
  387.             return(true);
  388.         }
  389.         return(false);
  390.     }
  391.  
  392.     // }}}
  393.     // {{{ _factory()
  394.  
  395.     /**
  396.      * Return a storage driver based on $driver and $options
  397.      *
  398.      * @static
  399.      * @param  string $driver  Type of storage class to return
  400.      * @param  string $options Optional parameters for the storage class
  401.      * @return object Object   Storage object
  402.      * @access private
  403.      */
  404.     function &_factory($driver, $options = '')
  405.     {
  406.         $storage_class = 'Auth_Container_' . $driver;
  407.         include_once 'Auth/Container/' . $driver . '.php';
  408.         $obj =& new $storage_class($options);
  409.         return $obj;
  410.     }
  411.  
  412.     // }}}
  413.     // {{{ assignData()
  414.  
  415.     /**
  416.      * Assign data from login form to internal values
  417.      *
  418.      * This function takes the values for username and password
  419.      * from $HTTP_POST_VARS/$_POST and assigns them to internal variables.
  420.      * If you wish to use another source apart from $HTTP_POST_VARS/$_POST,
  421.      * you have to derive this function.
  422.      *
  423.      * @global $HTTP_POST_VARS, $_POST
  424.      * @see    Auth
  425.      * @return void
  426.      * @access private
  427.      */
  428.     function assignData()
  429.     {
  430.         if (   isset($this->post[$this->_postUsername]) 
  431.             && $this->post[$this->_postUsername] != '') {
  432.             $this->username = (get_magic_quotes_gpc() == 1 
  433.                     ? stripslashes($this->post[$this->_postUsername]) 
  434.                     : $this->post[$this->_postUsername]);
  435.         }
  436.         if (   isset($this->post[$this->_postPassword]) 
  437.             && $this->post[$this->_postPassword] != '') {
  438.             $this->password = (get_magic_quotes_gpc() == 1 
  439.                     ? stripslashes($this->post[$this->_postPassword]) 
  440.                     : $this->post[$this->_postPassword] );
  441.         }
  442.     }
  443.  
  444.     // }}}
  445.     // {{{ start()
  446.  
  447.     /**
  448.      * Start new auth session
  449.      *
  450.      * @return void
  451.      * @access public
  452.      */
  453.     function start()
  454.     {
  455.         $this->assignData();
  456.         if (!$this->checkAuth() && $this->allowLogin) {
  457.             $this->login();
  458.         }
  459.     }
  460.  
  461.     // }}}
  462.     // {{{ login()
  463.  
  464.     /**
  465.      * Login function
  466.      *
  467.      * @return void
  468.      * @access private
  469.      */
  470.     function login()
  471.     {
  472.         $login_ok = false;
  473.         $this->_loadStorage();
  474.         
  475.         // Check if using challenge response
  476.         (isset($this->post['authsecret']) && $this->post['authsecret'] == 1) 
  477.             ? $usingChap = true 
  478.             : $usingChap = false;
  479.  
  480.         
  481.         // When the user has already entered a username, we have to validate it.
  482.         if (!empty($this->username)) {
  483.             if (true === $this->storage->fetchData($this->username, $this->password, $usingChap)) {
  484.                 $this->session['challengekey'] = md5($this->username.$this->password);
  485.                 $login_ok = true;
  486.             }
  487.         }
  488.  
  489.         if (!empty($this->username) && $login_ok) {
  490.             $this->setAuth($this->username);
  491.             if (is_callable($this->loginCallback)) {
  492.                 call_user_func_array($this->loginCallback, array($this->username, $this));
  493.             }
  494.         }
  495.  
  496.         // If the login failed or the user entered no username, 
  497.         // output the login screen again.
  498.         if (!empty($this->username) && !$login_ok) {
  499.             $this->status = AUTH_WRONG_LOGIN;
  500.             if (is_callable($this->loginFailedCallback)) {
  501.                 call_user_func_array($this->loginFailedCallback, array($this->username, $this));
  502.             }
  503.         }
  504.  
  505.         if ((empty($this->username) || !$login_ok) && $this->showLogin) {
  506.             if (is_callable($this->loginFunction)) {
  507.                 call_user_func_array($this->loginFunction, array($this->username, $this->status, $this));
  508.             } else {
  509.                 // BC fix Auth used to use drawLogin for this
  510.                 // call is sub classes implement this
  511.                 if (is_callable(array($this, 'drawLogin'))) {
  512.                     return $this->drawLogin($this->username, $this);
  513.                 }
  514.  
  515.                 // New Login form
  516.                 include_once 'Auth/Frontend/Html.php';
  517.                 return Auth_Frontend_Html::render($this, $this->username);
  518.             }
  519.         } else {
  520.             return;
  521.         }
  522.     }
  523.  
  524.     // }}}
  525.     // {{{ setExpire()
  526.  
  527.     /**
  528.      * Set the maximum expire time
  529.      *
  530.      * @param  integer time in seconds
  531.      * @param  bool    add time to current expire time or not
  532.      * @return void
  533.      * @access public
  534.      */
  535.     function setExpire($time, $add = false)
  536.     {
  537.         $add ? $this->expire += $time : $this->expire = $time;
  538.     }
  539.  
  540.     // }}}
  541.     // {{{ setIdle()
  542.  
  543.     /**
  544.      * Set the maximum idle time
  545.      *
  546.      * @param  integer time in seconds
  547.      * @param  bool    add time to current maximum idle time or not
  548.      * @return void
  549.      * @access public
  550.      */
  551.     function setIdle($time, $add = false)
  552.     {
  553.         $add ? $this->idle += $time : $this->idle = $time;
  554.     }
  555.  
  556.     // }}}
  557.     // {{{ setSessionName()
  558.  
  559.     /**
  560.      * Set name of the session to a customized value.
  561.      *
  562.      * If you are using multiple instances of PEAR::Auth
  563.      * on the same domain, you can change the name of
  564.      * session per application via this function.
  565.      * This will chnage the name of the session variable 
  566.      * auth uses to store it's data in the session
  567.      *
  568.      * @param  string New name for the session
  569.      * @return void
  570.      * @access public
  571.      */
  572.     function setSessionName($name = 'session')
  573.     {
  574.         $this->_sessionName = '_auth_'.$name;
  575.         isset($_SESSION) 
  576.             ? $this->session =& $_SESSION[$this->_sessionName] 
  577.             : $this->session =& $GLOBALS['HTTP_SESSION_VARS'][$this->_sessionName] ;
  578.     }
  579.  
  580.     // }}}
  581.     // {{{ setShowLogin()
  582.  
  583.     /**
  584.      * Should the login form be displayed if neccessary?
  585.      *
  586.      * @param  bool    show login form or not
  587.      * @return void
  588.      * @access public
  589.      */
  590.     function setShowLogin($showLogin = true)
  591.     {
  592.         $this->showLogin = $showLogin;
  593.     }
  594.  
  595.     // }}}
  596.     // {{{ setAllowLogin()
  597.  
  598.     /**
  599.      * Should the login form be displayed if neccessary?
  600.      *
  601.      * @param  bool    show login form or not
  602.      * @return void
  603.      * @access public
  604.      */
  605.     function setAllowLogin($allowLogin = true)
  606.     {
  607.         $this->allowLogin = $allowLogin;
  608.     }
  609.  
  610.     // }}}
  611.     // {{{ setLoginCallback()
  612.     
  613.     /**
  614.      * Register a callback function to be called on user login.
  615.      * The function will receive two parameters, the username and a reference to the auth object.
  616.      *
  617.      * @param  string  callback function name
  618.      * @return void
  619.      * @see    setLogoutCallback()
  620.      * @access public
  621.      */
  622.     function setLoginCallback($loginCallback)
  623.     {
  624.         $this->loginCallback = $loginCallback;
  625.     }
  626.  
  627.     // }}}
  628.     // {{{ setFailedLoginCallback()
  629.  
  630.     /**
  631.      * Register a callback function to be called on failed user login.
  632.      * The function will receive a single parameter, the username and a reference to the auth object.
  633.      *
  634.      * @param  string  callback function name
  635.      * @return void
  636.      * @access public
  637.      */
  638.     function setFailedLoginCallback($loginFailedCallback)
  639.     {
  640.         $this->loginFailedCallback = $loginFailedCallback;
  641.     }
  642.  
  643.     // }}}
  644.     // {{{ setLogoutCallback()
  645.  
  646.     /**
  647.      * Register a callback function to be called on user logout.
  648.      * The function will receive three parameters, the username and a reference to the auth object.
  649.      *
  650.      * @param  string  callback function name
  651.      * @return void
  652.      * @see    setLoginCallback()
  653.      * @access public
  654.      */
  655.     function setLogoutCallback($logoutCallback)
  656.     {
  657.         $this->logoutCallback = $logoutCallback;
  658.     }
  659.  
  660.     // }}}
  661.     // {{{ setAuthData()
  662.  
  663.     /**
  664.      * Register additional information that is to be stored
  665.      * in the session.
  666.      *
  667.      * @param  string  Name of the data field
  668.      * @param  mixed   Value of the data field
  669.      * @param  boolean Should existing data be overwritten? (default
  670.      *                 is true)
  671.      * @return void
  672.      * @access public
  673.      */
  674.     function setAuthData($name, $value, $overwrite = true)
  675.     {
  676.         if (!empty($this->session['data'][$name]) && $overwrite == false) {
  677.             return;
  678.         }
  679.         $this->session['data'][$name] = $value;
  680.     }
  681.  
  682.     // }}}
  683.     // {{{ getAuthData()
  684.  
  685.     /**
  686.      * Get additional information that is stored in the session.
  687.      *
  688.      * If no value for the first parameter is passed, the method will
  689.      * return all data that is currently stored.
  690.      *
  691.      * @param  string Name of the data field
  692.      * @return mixed  Value of the data field.
  693.      * @access public
  694.      */
  695.     function getAuthData($name = null)
  696.     {
  697.         if (!isset($this->session['data'])) {
  698.             return null;
  699.         }    
  700.         if(!isset($name)) {
  701.             return $this->session['data'];
  702.         }
  703.         if (isset($name) && isset($this->session['data'][$name])) {
  704.             return $this->session['data'][$name];
  705.         }
  706.         return null;        
  707.     }
  708.  
  709.     // }}}
  710.     // {{{ setAuth()
  711.  
  712.     /**
  713.      * Register variable in a session telling that the user
  714.      * has logged in successfully
  715.      *
  716.      * @param  string Username
  717.      * @return void
  718.      * @access public
  719.      */
  720.     function setAuth($username)
  721.     {
  722.     
  723.         // #2021 - Change the session id to avoid session fixation attacks php 4.3.3 > 
  724.         session_regenerate_id();
  725.  
  726.         if (!isset($this->session) || !is_array($this->session)) {
  727.             $this->session = array();
  728.         }
  729.  
  730.         if (!isset($this->session['data'])) {
  731.             $this->session['data'] = array();
  732.         }
  733.  
  734.         $this->session['sessionip'] = isset($this->server['REMOTE_ADDR']) 
  735.             ? $this->server['REMOTE_ADDR'] 
  736.             : '';
  737.         $this->session['sessionuseragent'] = isset($this->server['HTTP_USER_AGENT']) 
  738.             ? $this->server['HTTP_USER_AGENT'] 
  739.             : '';
  740.  
  741.         // This should be set by the container to something more safe
  742.         // Like md5(passwd.microtime)
  743.         if(empty($this->session['challengekey'])) {
  744.             $this->session['challengekey'] = md5($username.microtime());
  745.         }
  746.  
  747.         $this->session['challengecookie'] = md5($this->session['challengekey'].microtime());
  748.         setcookie('authchallenge', $this->session['challengecookie']);
  749.  
  750.         $this->session['registered'] = true;
  751.         $this->session['username']   = $username;
  752.         $this->session['timestamp']  = time();
  753.         $this->session['idle']       = time();
  754.     }
  755.  
  756.     // }}}
  757.     // {{{ setAdvancedSecurity()
  758.     
  759.     /**
  760.       * Enables advanced security checks
  761.       *
  762.       * Currently only ip change and useragent change 
  763.       * are detected
  764.       * @todo Add challenge cookies - Create a cookie which changes every time 
  765.       *       and contains some challenge key which the server can verify with
  766.       *       a session var cookie might need to be crypted (user pass)
  767.       * @param bool Enable or disable
  768.       * @return void
  769.       * @access public
  770.       */
  771.     function setAdvancedSecurity($flag=true)
  772.     {
  773.         $this->advancedsecurity = $flag;
  774.     }
  775.  
  776.     // }}}
  777.     // {{{ checkAuth()
  778.  
  779.     /**
  780.      * Checks if there is a session with valid auth information.
  781.      *
  782.      * @access public
  783.      * @return boolean  Whether or not the user is authenticated.
  784.      */
  785.     function checkAuth()
  786.     {
  787.         $this->authChecks++;
  788.         if (isset($this->session)) {
  789.             // Check if authentication session is expired
  790.             if (   $this->expire > 0
  791.                 && isset($this->session['timestamp'])
  792.                 && ($this->session['timestamp'] + $this->expire) < time()) {
  793.                 $this->expired = true;
  794.                 $this->status = AUTH_EXPIRED;
  795.                 $this->logout();
  796.                 return false;
  797.             }
  798.  
  799.             // Check if maximum idle time is reached
  800.             if (   $this->idle > 0
  801.                 && isset($this->session['idle']) 
  802.                 && ($this->session['idle'] + $this->idle) < time()) {
  803.                 $this->idled = true;
  804.                 $this->status = AUTH_IDLED;
  805.                 $this->logout();
  806.                 return false;
  807.             }
  808.  
  809.             if (   isset($this->session['registered']) 
  810.                 && isset($this->session['username']) 
  811.                 && $this->session['registered'] == true 
  812.                 && $this->session['username'] != '') {
  813.                 Auth::updateIdle();
  814.  
  815.                 if ($this->advancedsecurity) {
  816.                     
  817.                     // Only Generate the challenge once
  818.                     if($this->authChecks == 1) {
  819.                         $this->session['challengecookieold'] = $this->session['challengecookie'];
  820.                         $this->session['challengecookie'] = md5($this->session['challengekey'].microtime());
  821.                         setcookie('authchallenge', $this->session['challengecookie']);
  822.                     }
  823.                     
  824.                     // Check for ip change
  825.                     if (   isset($this->server['REMOTE_ADDR']) 
  826.                         && $this->session['sessionip'] != $this->server['REMOTE_ADDR']) {
  827.                         // Check if the IP of the user has changed, if so we 
  828.                         // assume a man in the middle attack and log him out
  829.                         $this->expired = true;
  830.                         $this->status = AUTH_SECURITY_BREACH;
  831.                         $this->logout();
  832.                         return false;
  833.                     }
  834.                     
  835.                     // Check for useragent change
  836.                     if (   isset($this->server['HTTP_USER_AGENT']) 
  837.                         && $this->session['sessionuseragent'] != $this->server['HTTP_USER_AGENT']) {
  838.                         // Check if the User-Agent of the user has changed, if 
  839.                         // so we assume a man in the middle attack and log him out
  840.                         $this->expired = true;
  841.                         $this->status = AUTH_SECURITY_BREACH;
  842.                         $this->logout();
  843.                         return false;
  844.                     }
  845.     
  846.                     // Check challenge cookie here, if challengecookieold is not set 
  847.                     // this is the first time and check is skipped
  848.                     // TODO when user open two pages similtaneuly (open in new window,open 
  849.                     // in tab) auth breach is caused find out a way around that if possible
  850.                     if (   isset($this->session['challengecookieold']) 
  851.                         && $this->session['challengecookieold'] != $this->cookie['authchallenge']) {
  852.                         $this->expired = true;
  853.                         $this->status = AUTH_SECURITY_BREACH;
  854.                         $this->logout();
  855.                         $this->login();
  856.                         return false;
  857.                     }
  858.                 }
  859.  
  860.                 return true;
  861.             }
  862.         }
  863.         return false;
  864.     }
  865.  
  866.     // }}}
  867.     // {{{ staticCheckAuth() [static]
  868.  
  869.     /**
  870.      * Statically checks if there is a session with valid auth information.
  871.      *
  872.      * @access public
  873.      * @see checkAuth
  874.      * @return boolean  Whether or not the user is authenticated.
  875.      * @static
  876.      */
  877.     function staticCheckAuth($options = null)
  878.     {
  879.         static $staticAuth;
  880.         if(!isset($staticAuth)) {
  881.             $staticAuth = new Auth('null', $options);
  882.         }
  883.         return $staticAuth->checkAuth();
  884.     }
  885.  
  886.     // }}}
  887.     // {{{ getAuth()
  888.  
  889.     /**
  890.      * Has the user been authenticated?
  891.      *
  892.      * @access public
  893.      * @return bool  True if the user is logged in, otherwise false.
  894.      */
  895.     function getAuth()
  896.     {
  897.         return $this->checkAuth();
  898.     }
  899.  
  900.     // }}}
  901.     // {{{ logout()
  902.  
  903.     /**
  904.      * Logout function
  905.      *
  906.      * This function clears any auth tokens in the currently
  907.      * active session and executes the logout callback function,
  908.      * if any
  909.      *
  910.      * @access public
  911.      * @return void
  912.      */
  913.     function logout()
  914.     {
  915.         if (is_callable($this->logoutCallback)) {
  916.             call_user_func_array($this->logoutCallback, array($this->session['username'], $this));
  917.         }
  918.  
  919.         $this->username = '';
  920.         $this->password = '';
  921.         
  922.         $this->session = null;
  923.     }
  924.  
  925.     // }}}
  926.     // {{{ updateIdle()
  927.  
  928.     /**
  929.      * Update the idletime
  930.      *
  931.      * @access private
  932.      * @return void
  933.      */
  934.     function updateIdle()
  935.     {
  936.         $this->session['idle'] = time();
  937.     }
  938.  
  939.     // }}}
  940.     // {{{ getUsername()
  941.  
  942.     /**
  943.      * Get the username
  944.      *
  945.      * @return string
  946.      * @access public
  947.      */
  948.     function getUsername()
  949.     {
  950.         if (isset($this->session['username'])) {
  951.             return($this->session['username']);
  952.         }
  953.         return('');
  954.     }
  955.  
  956.     // }}}
  957.     // {{{ getStatus()
  958.  
  959.     /**
  960.      * Get the current status
  961.      *
  962.      * @return string
  963.      * @access public
  964.      */
  965.     function getStatus()
  966.     {
  967.         return $this->status;
  968.     }
  969.  
  970.     // }}}
  971.     // {{{ getPostUsernameField()
  972.     
  973.     /**
  974.      * Gets the post varible used for the username
  975.      * 
  976.      * @return string
  977.      * @access public
  978.      */
  979.     function getPostUsernameField()
  980.     {
  981.         return($this->_postUsername);
  982.     }
  983.  
  984.     // }}}
  985.     // {{{ getPostPasswordField()
  986.  
  987.     /**
  988.      * Gets the post varible used for the username
  989.      * 
  990.      * @return string
  991.      * @access public
  992.      */
  993.     function getPostPasswordField()
  994.     {
  995.         return($this->_postPassword);
  996.     }
  997.  
  998.     // }}}
  999.     // {{{ sessionValidThru()
  1000.  
  1001.     /**
  1002.      * Returns the time up to the session is valid
  1003.      *
  1004.      * @access public
  1005.      * @return integer
  1006.      */
  1007.     function sessionValidThru()
  1008.     {
  1009.         if (!isset($this->session['idle'])) {
  1010.             return 0;
  1011.         }
  1012.         return ($this->session['idle'] + $this->idle);
  1013.     }
  1014.  
  1015.     // }}}
  1016.     // {{{ listUsers()
  1017.  
  1018.     /**
  1019.      * List all users that are currently available in the storage
  1020.      * container
  1021.      *
  1022.      * @access public
  1023.      * @return array
  1024.      */
  1025.     function listUsers()
  1026.     {
  1027.         $this->_loadStorage();
  1028.         return $this->storage->listUsers();
  1029.     }
  1030.  
  1031.     // }}}
  1032.     // {{{ addUser()
  1033.  
  1034.     /**
  1035.      * Add user to the storage container
  1036.      *
  1037.      * @access public
  1038.      * @param  string Username
  1039.      * @param  string Password
  1040.      * @param  mixed  Additional parameters
  1041.      * @return mixed  True on success, PEAR error object on error
  1042.      *                and AUTH_METHOD_NOT_SUPPORTED otherwise.
  1043.      */
  1044.     function addUser($username, $password, $additional = '')
  1045.     {
  1046.         $this->_loadStorage();
  1047.         return $this->storage->addUser($username, $password, $additional);
  1048.     }
  1049.  
  1050.     // }}}
  1051.     // {{{ removeUser()
  1052.  
  1053.     /**
  1054.      * Remove user from the storage container
  1055.      *
  1056.      * @access public
  1057.      * @param  string Username
  1058.      * @return mixed  True on success, PEAR error object on error
  1059.      *                and AUTH_METHOD_NOT_SUPPORTED otherwise.
  1060.      */
  1061.     function removeUser($username)
  1062.     {
  1063.         $this->_loadStorage();
  1064.         return $this->storage->removeUser($username);
  1065.     }
  1066.  
  1067.     // }}}
  1068.     // {{{ changePassword()
  1069.  
  1070.     /**
  1071.      * Change password for user in the storage container
  1072.      *
  1073.      * @access public
  1074.      * @param string Username
  1075.      * @param string The new password 
  1076.      * @return mixed True on success, PEAR error object on error
  1077.      *               and AUTH_METHOD_NOT_SUPPORTED otherwise.
  1078.      */
  1079.     function changePassword($username, $password)
  1080.     {
  1081.         $this->_loadStorage();
  1082.         return $this->storage->changePassword($username, $password);
  1083.     }
  1084.  
  1085.     // }}}
  1086.  
  1087. }
  1088. ?>
  1089.